// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraGameplayEffectContext.h"

#include "AbilitySystem/LyraAbilitySourceInterface.h"
#include "Engine/HitResult.h"
#include "PhysicalMaterials/PhysicalMaterial.h"

// Controls whether Iris networking code is compiled in or not; should normally be defined by UBT

// UE_WITH_IRIS: 控制是否编辑Iris网络代码；通常是被UBT定义。宏通常在Build.h文件夹内。
#if UE_WITH_IRIS
/**
 * Currently we require each supported type to register FPropertyNetSerializerInfo
 * It provides information on what NetSerializer to use for which property and how to build the required NetSerializer config which is used when we build the dynamic descriptor
 * It is possible to register multiple FPropertyNetSerializerInfo for the same PropertyType-class as long as the IsSupportedFunction only matches a single Property, i.e. bool/nativebool enums of different sizes
 */

/**
 * FPropertyNetSerializerInfo: 
 * 当前我们请求的每个支持去注册FPropertyNetSerializerInfo的类型。
 * 它提供NetSerializer去使用那个属性的信息并且构建了请求NetSerializer的用于我们构建动态描述符的配置。
 * 它尽可能去注册多种FPropertyNetSerializerInfo对于相同属性类型的类，在IsSupportedFunction仅匹配单个属性的情况下。
 */
#include "Iris/ReplicationState/PropertyNetSerializerInfoRegistry.h"
#include "Serialization/GameplayEffectContextNetSerializer.h"
#endif

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraGameplayEffectContext)

class FArchive;

FLyraGameplayEffectContext* FLyraGameplayEffectContext::ExtractEffectContext(struct FGameplayEffectContextHandle Handle)
{
	FGameplayEffectContext* BaseEffectContext = Handle.Get();
	/** Returns the actual struct used for serialization, subclasses must override this! */

	/** GetScriptStruct: 返回用于序列化的实际结构体，子类必须覆盖它。 */

	/** Returns true if this struct either is SomeBase, or is a child of SomeBase. This will not crash on null structs */

	/** IsChildOf: 如果结构体是SomeBase本身或者是SomeBase子类，则返回True。对于空结构体，此函数不会导致程序崩溃。 */

	/**
	 * Reflection data for a standalone structure declared in a header or as a user defined struct
	 */

	/**
	 * UScriptStruct: 
	 * 对于单独结构体定义在头文件或作为用户定义的结构体的反射数据。在Class.h文件中定义。
	 */
	if ((BaseEffectContext != nullptr) && BaseEffectContext->GetScriptStruct()->IsChildOf(FLyraGameplayEffectContext::StaticStruct()))
	{
		return (FLyraGameplayEffectContext*)BaseEffectContext;
	}

	return nullptr;
}

bool FLyraGameplayEffectContext::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
	FGameplayEffectContext::NetSerialize(Ar, Map, bOutSuccess);

	// Not serialized for post-activation use:
	// CartridgeID

	return true;
}

#if UE_WITH_IRIS
namespace UE::Net
{
	// Forward to FGameplayEffectContextNetSerializer
	// Note: If FLyraGameplayEffectContext::NetSerialize() is modified, a custom NetSerializesr must be implemented as the current fallback will no longer be sufficient.
	UE_NET_IMPLEMENT_FORWARDING_NETSERIALIZER_AND_REGISTRY_DELEGATES(LyraGameplayEffectContext, FGameplayEffectContextNetSerializer);

	// 将数据转给FGameplayEffectContextNetSerializer处理。
	// Note: 如果FLyraGameplayEffectContext::NetSerialize()是被修改的，一个自定义的NetSerializesr必须被实现因为当前回退机制将不够使用。
}
#endif

void FLyraGameplayEffectContext::SetAbilitySource(const ILyraAbilitySourceInterface* InObject, float InSourceLevel)
{
	AbilitySourceObject = MakeWeakObjectPtr(Cast<const UObject>(InObject));
	//SourceLevel = InSourceLevel;
}

const ILyraAbilitySourceInterface* FLyraGameplayEffectContext::GetAbilitySource() const
{
	return Cast<ILyraAbilitySourceInterface>(AbilitySourceObject.Get());
}

const UPhysicalMaterial* FLyraGameplayEffectContext::GetPhysicalMaterial() const
{
	if (const FHitResult* HitResultPtr = GetHitResult())
	{
		return HitResultPtr->PhysMaterial.Get();
	}
	return nullptr;
}

